﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AVL
{
    public partial class AVL : Form
    {

        AVLTree ATree = new AVLTree();

        //AVLTree ATreeLeft = new AVLTree();

        AVLTree ATreeRight = new AVLTree();

        AVLTree current;

        public AVL()
        {
            InitializeComponent();
            current = ATree;
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }

        private void button5_Click(object sender, EventArgs e)
        {
            if (!current.ava)
            {
                printf("！需要调整平衡后再操作");
                return;
            }
            current.mergeAVLTree(ATree, ATreeRight);
            printf("树 A 与 树 B 合并完毕");
            //Graphics g = this.richTextBox3.CreateGraphics();//得到窗体使用的Graphics类对象
            //current.paintAVLByStack(g);
            //g.Dispose();

            //Pen pen1 = new Pen(Color.Red);//创建红色笔对象
            //SolidBrush brush1 = new SolidBrush(Color.Blue);//创建蓝色刷子对象
            //SolidBrush brush2 = new SolidBrush(Color.Yellow);//创建蓝色刷子对象
            //SolidBrush brush3 = new SolidBrush(Color.Red);//创建蓝色刷子对象
            //g.DrawEllipse(pen1, 400 - 30, 30, 60, 60);//用红色笔画圆的边界
            //g.FillEllipse(brush1, 400 - 30, 30, 60, 60);//用蓝色刷子填充圆的内部

            //Font drawFont = new Font("Arial", 16);
            //PointF drawPoint = new PointF(400, 10 + 30);
            //g.DrawString("7", drawFont, brush2, drawPoint);
            //g.DrawString("1", drawFont, brush3, new PointF(400 - 40, 30));
            //g.DrawString("1", drawFont, brush3, new PointF(400 + 40, 30));

            //Pen p = new Pen(Color.Blue, 2);

            //g.DrawLine(p, 100, 30, 70, 60);

            //  画虚线
            //Pen pen2 = new Pen(Color.Blue, 12);
            //pen2.DashStyle = DashStyle.Custom;
            //pen2.DashPattern = new float[] { 1f, 1f };
            //Graphics g2 = this.CreateGraphics();
            //g2.DrawLine(pen2, 10, 150, 500, 150);

        }

        /// <summary>
        /// 插入 新节点
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            int data = getInput();
            if (data == int.MaxValue) return;

            if (!current.ava)
            {
                printf("！需要调整平衡后再操作");
                return;
            }
            current.opadd = true;
            if (current.insert(data) != -1)
            {
                printf("插入的节点值为" + data);

            }
            else
            {
                printf("插入的节点值" + data + "已经存在");
            }
            if(current.A != null )
            {
                current.ava = false;
            }
          
            Graphics g = this.richTextBox3.CreateGraphics();
            g.Clear(Color.White);
            current.paintAVLByStack(g);
            g.Dispose();
        }

        /// <summary>
        /// 清空树
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button8_Click(object sender, EventArgs e)
        {
            if (current != ATreeRight) ATree.root = null;
            else ATreeRight.root = null;
            printf("AVL树 已经清空");
            Graphics g = this.richTextBox3.CreateGraphics();
            g.Clear(Color.White);
            g.Dispose();
        }



        /// <summary>
        ///  当新写入内容时，超过当前显示区域后，自动滚动到最低端
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
 
        private void richTextBox1_TextChanged(object sender, EventArgs e)
        {
            richTextBox1.SelectionStart = richTextBox1.Text.Length; //Set the current caret position at the end
            richTextBox1.ScrollToCaret(); //Now scroll it automatically
        }

        /// <summary>
        /// 
        /// 删除 操作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            int data = getInput();
            if (data == int.MaxValue) return;
            if (!current.ava)
            {
                printf("！需要调整平衡后再操作");
                return;
            }
            current.opadd = false;
            
            AVLNode node = current.find(data);
            repaint();
            //
            Thread.Sleep(1000);
            current.resetcolor(current.root);
            //
            if (node != null) { 
                current.delete(node);
                printf("删除的节点值为" + data);
            }else
            {
                printf("该节点不存在");
            }
            if (current.A != null)
            {
                current.ava = false;
            }
            repaint();
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AVL_Load(object sender, EventArgs e)
        {
           
        }


        /// <summary>
        /// 清空 输出窗口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button7_Click(object sender, EventArgs e)
        {
            this.richTextBox1.Text = "";
        }


        /// <summary>
        /// 调整AVLTree
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            if (current.A == null)
            {
                printf("该树已经平衡、不用再调整");
                return;
            }
           printf(current.next());
           if (current.A == null)
           {
               current.ava = true;
               printf("调整完成");
           }
            Graphics g = this.richTextBox3.CreateGraphics();
            g.Clear(Color.White);
            current.paintAVLByStack(g);
            g.Dispose();
        }

        /// <summary>
        /// 查找
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            int data = getInput();
            if (data == int.MaxValue) return;
            AVLNode B = current.find(data);
            if (B != null) {
                B.color = Color.Blue;
                repaint();
                current.resetcolor(current.root);
                this.richTextBox1.Text = this.richTextBox1.Text + "[" + DateTime.Now.ToLocalTime().ToString() + "] :" + "查找的接点为蓝色节点" + B.data + "\n";
            }
            else { 
                   this.richTextBox1.Text = this.richTextBox1.Text + "[" + DateTime.Now.ToLocalTime().ToString() + "] : 值为" + data + "的接点不存在" + "\n";
            }
        }

        /// <summary>
        /// 重画画板
        /// </summary>
        public void repaint() {
            if (current == null) return;
            Graphics g = this.richTextBox3.CreateGraphics();
            g.Clear(Color.White);
            current.paintAVLByStack(g);
            g.Dispose();
        }

        /// <summary>
        /// 自动生成AVLTree
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button6_Click(object sender, EventArgs e)
        {
            if (current != ATreeRight)
            {
                current = ATree;
            }
            int i, data;
            for (i = 0; i < 10; i++) {
                long tick = DateTime.Now.Ticks;
                Random ro = new Random((int)(tick & 0xffffffffL) | (int)(tick >> 32));
                data = ro.Next(100);
                // 
                adjustTree(data);

                Thread.Sleep(1000);
                printf("插入节点值为" + data);
            }
           
        }

        //   AVLTree 插入一个节点并调整
        public void adjustTree(int data){
            if (current.ava)
            {
                // 声明为 插入操作
                current.opadd = true;
                current.insert(data);
            }
            current.optop = 0;
            for (int j = 1; j <= 4; j++)
            {
                // 说明 为RR 或 LL   twice  没有改变    //  twice 为false 不用 两次
                if (j == 3 && !current.twice)
                    break;
                string info = current.next();
                if (!info.Equals("")) printf(info);
                repaint();
                Thread.Sleep(500);
                if (current.A == null)
                    break;
            }
            //     current.updateHight(current.root);
            repaint();
        
        }


        //  切换 当前操作对象
    

        private void button10_Click(object sender, EventArgs e)
        {
            current = ATree;
            repaint();
        }

        private void button12_Click(object sender, EventArgs e)
        {
            current = ATreeRight;
            repaint();
        }


        /// <summary>
        /// 分裂二叉树
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button9_Click(object sender, EventArgs e)
        {
            int data = getInput();
            if (data == int.MaxValue) return;
            if (!current.ava)
            {
                printf("！需要调整平衡后再操作");
                return;
            }
            current.split(data);
            ATree.root = current.one.root;
            ATreeRight.root = current.other.root;
            repaint();
            printf("以" + data + "接点分裂为两棵平衡二叉树完成");
        }

        /// <summary>
        ///  输出 info
        /// </summary>
        /// <param name="info"></param>
        private void  printf(string info){
            string treeName = "A :";
            if (current != ATree) {
                treeName = "B ：";
            }
            this.richTextBox1.Text = this.richTextBox1.Text + "[" + DateTime.Now.ToLocalTime().ToString() + "]" + treeName + info + "\n";
        }

        private int getInput()
        {
            int data = int.MaxValue;
            try
            {
                data = int.Parse(this.textBox1.Text);
            }
            catch (Exception e){
                printf("请输入正整数！");
            }

            return data;
        }

    }
}
